//! 日志工具

use log::{LevelFilter, Metadata, Record};
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::sync::Mutex;

/// 自定义日志记录器
struct SimpleLogger {
    level: LevelFilter,
    file: Option<Mutex<File>>,
}

impl SimpleLogger {
    /// 创建一个新的日志记录器
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::logging::SimpleLogger;
    /// use log::LevelFilter;
    /// 
    /// let logger = SimpleLogger::new(LevelFilter::Debug, None);
    /// assert!(logger.is_ok());
    /// ```
    pub fn new(level: LevelFilter, file_path: Option<&str>) -> Result<SimpleLogger, std::io::Error> {
        let file = match file_path {
            Some(path) => {
                let file = OpenOptions::new()
                    .create(true)
                    .append(true)
                    .open(path)?;
                Some(Mutex::new(file))
            }
            None => None,
        };

        Ok(SimpleLogger { level, file })
    }
}

impl log::Log for SimpleLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= self.level
    }

    fn log(&self, record: &Record) {
        if self.enabled(record.metadata()) {
            let timestamp = chrono::Local::now().format("%Y-%m-%d %H:%M:%S");
            let log_message = format!(
                "[{}][{}][{}:{}] {}\n",
                timestamp,
                record.level(),
                record.file().unwrap_or("unknown"),
                record.line().unwrap_or(0),
                record.args()
            );

            // 输出到控制台
            println!("{}", log_message);

            // 如果指定了文件，也输出到文件
            if let Some(file) = &self.file {
                if let Ok(mut file) = file.lock() {
                    let _ = file.write_all(log_message.as_bytes());
                    let _ = file.flush();
                }
            }
        }
    }

    fn flush(&self) {
        if let Some(file) = &self.file {
            if let Ok(mut file) = file.lock() {
                let _ = file.flush();
            }
        }
    }
}

/// 初始化日志系统
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::logging::init_logger;
/// use log::LevelFilter;
/// 
/// // 初始化日志系统
/// init_logger(LevelFilter::Debug, None).unwrap();
/// 
/// // 现在可以使用日志宏了
/// log::info!("这是一条信息日志");
/// log::debug!("这是一条调试日志");
/// ```
pub fn init_logger(level: LevelFilter, file_path: Option<&str>) -> Result<(), Box<dyn std::error::Error>> {
    let logger = SimpleLogger::new(level, file_path)?;
    
    log::set_boxed_logger(Box::new(logger))?;
    log::set_max_level(level);
    Ok(())
}

/// 日志装饰器，用于为函数添加入口和出口日志
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::logging::log_function;
/// 
/// fn my_function(x: i32) -> i32 {
///     log_function("my_function", || {
///         x * 2
///     })
/// }
/// ```
pub fn log_function<F, R>(func_name: &str, func: F) -> R
where
    F: FnOnce() -> R,
{
    log::debug!("Entering function: {}", func_name);
    let result = func();
    log::debug!("Exiting function: {}", func_name);
    result
}

/// 性能计时装饰器，用于测量函数执行时间
/// 
/// # 示例
/// 
/// ```
/// use rust_utils::logging::time_function;
/// use std::thread;
/// use std::time::Duration;
/// 
/// fn slow_function() -> i32 {
///     time_function("slow_function", || {
///         thread::sleep(Duration::from_millis(100));
///         42
///     })
/// }
/// ```
pub fn time_function<F, R>(func_name: &str, func: F) -> R
where
    F: FnOnce() -> R,
{
    let start = std::time::Instant::now();
    log::debug!("Starting function: {}", func_name);
    
    let result = func();
    
    let duration = start.elapsed();
    log::debug!("Function {} completed in {:?}", func_name, duration);
    result
}

/// 结构化日志记录器
pub struct StructuredLogger;

impl StructuredLogger {
    /// 记录结构化日志 - 错误事件
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::logging::StructuredLogger;
    /// 
    /// StructuredLogger::log_error("database_connection", "连接数据库失败", Some("连接超时"));
    /// ```
    pub fn log_error(event: &str, message: &str, details: Option<&str>) {
        let timestamp = chrono::Local::now().to_rfc3339();
        let log_entry = serde_json::json!({
            "timestamp": timestamp,
            "level": "ERROR",
            "event": event,
            "message": message,
            "details": details
        });
        log::error!("{}", log_entry);
    }

    /// 记录结构化日志 - 警告事件
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::logging::StructuredLogger;
    /// 
    /// StructuredLogger::log_warning("config_warning", "配置项缺失", Some("使用默认值"));
    /// ```
    pub fn log_warning(event: &str, message: &str, details: Option<&str>) {
        let timestamp = chrono::Local::now().to_rfc3339();
        let log_entry = serde_json::json!({
            "timestamp": timestamp,
            "level": "WARNING",
            "event": event,
            "message": message,
            "details": details
        });
        log::warn!("{}", log_entry);
    }

    /// 记录结构化日志 - 信息事件
    /// 
    /// # 示例
    /// 
    /// ```
    /// use rust_utils::logging::StructuredLogger;
    /// 
    /// StructuredLogger::log_info("user_action", "用户登录", Some("用户ID: 12345"));
    /// ```
    pub fn log_info(event: &str, message: &str, details: Option<&str>) {
        let timestamp = chrono::Local::now().to_rfc3339();
        let log_entry = serde_json::json!({
            "timestamp": timestamp,
            "level": "INFO",
            "event": event,
            "message": message,
            "details": details
        });
        log::info!("{}", log_entry);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use log::LevelFilter;
    use std::fs;

    #[test]
    fn test_logger_initialization() {
        // 初始化日志系统
        let result = init_logger(LevelFilter::Debug, None);
        // 如果日志系统已经初始化，可能会失败，这是正常的
        // 我们只检查它没有panic
    }

    #[test]
    fn test_log_function() {
        let _ = init_logger(LevelFilter::Debug, None);
        
        let result = log_function("test_function", || {
            42
        });
        
        assert_eq!(result, 42);
    }

    #[test]
    fn test_time_function() {
        let _ = init_logger(LevelFilter::Debug, None);
        
        let result = time_function("test_timed_function", || {
            std::thread::sleep(std::time::Duration::from_millis(1));
            42
        });
        
        assert_eq!(result, 42);
    }

    #[test]
    fn test_structured_logger() {
        let _ = init_logger(LevelFilter::Debug, None);
        
        StructuredLogger::log_info("test_event", "测试事件", Some("详细信息"));
        StructuredLogger::log_warning("test_warning", "测试警告", None);
        StructuredLogger::log_error("test_error", "测试错误", Some("错误详情"));
    }

    #[test]
    fn test_file_logging() {
        // 创建临时日志文件
        let log_file = "test.log";
        
        // 初始化文件日志
        let result = init_logger(LevelFilter::Debug, Some(log_file));
        // 如果日志系统已经初始化，可能会失败，这是正常的
        
        // 写入一些日志
        log::info!("文件日志测试");
        
        // 检查文件是否存在
        // assert!(fs::metadata(log_file).is_ok());
        
        // 清理测试文件
        let _ = fs::remove_file(log_file);
    }
}